package com.zxw.java基础.线程.waitAndNotify;

/**
 * 在上述示例中，Message类是一个共享的消息类，其中使用synchronized关键字修饰了getContent()和setContent()方法，以确保它们的原子性操作。
 * Waiter类是一个等待线程，调用message.getContent()来等待并获取消息内容。当调用wait()方法时，线程会进入等待状态，直到其他线程调用notify()或notifyAll()方法唤醒它。
 * Notifier类是一个通知线程，调用message.setContent(content)来设置消息内容，并通过调用notifyAll()方法唤醒处于等待状态的线程。
 * 当运行这个示例代码时，你会看到Waiter线程等待并接收到了Notifier线程发送的消息内容。
 * 需要注意的是，wait()和notify()方法必须在同步代码块或同步方法中使用，因为它们依赖于对象的监视器锁（也称为内置锁）来实现线程间的协调与通信。
 *
 * @projectName: util-cloud
 * @package: com.zxw.java基础.线程.waitAndNotify
 * @className: R
 * @author: zhangxuewei
 * @description: TODO
 * @date: 2023/10/31 12:54
 * @version: 1.0
 */
public class ThreadWaitNotifyExample {

    public static void main(String[] args) {
        Message message = new Message();

        // 创建一个等待线程，并启动
        Thread waiterThread = new Thread(new Waiter(message));
        waiterThread.start();

        // 创建一个通知线程，并启动
        Thread notifierThread = new Thread(new Notifier(message));
        notifierThread.start();
    }
}

// 共享的消息类
class Message {
    private String content;

    public synchronized String getContent() {
        while (content == null) { // 当content为null时，等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        String message = content;
        content = null; // 重置content为null
        notifyAll(); // 唤醒其他等待线程
        return message;
    }

    public synchronized void setContent(String content) {
        while (this.content != null) { // 当content不为null时，等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.content = content;
        notifyAll(); // 唤醒其他等待线程
    }
}

// 等待线程
class Waiter implements Runnable {
    private Message message;

    public Waiter(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        String receivedMessage = message.getContent();
        System.out.println("Waiter received message: " + receivedMessage);
    }
}

// 通知线程
class Notifier implements Runnable {
    private Message message;

    public Notifier(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        String content = "Hello, World!";
        System.out.println("set context:" + content);
        message.setContent(content);
        System.out.println("Notifier sent message: " + content);
    }
}
